﻿DrawBoard();
MoveHighlight();
HighlightMoved();
CheckSquare();
AdjacentSquares();
ClearBoardCheck();
ClickScore();
ColorSquare();
UpdateScore();
RemoveGroup();
ShiftCircles();
ColorCircle();
BlackSquare();
IsGameOver();
ClearGameOver();
UpdateHighScore();
IntToString();
DigitToChar();
IsGroup();

colorList;
highlightColorList;
difficultyList;
boardColor;
boardCheck;
highlightindex;
score;
clickscore;
highscore;

EXPORT SameGame()
//SameGame v1.4
//2024
//Tony Gallo
//tgallo@tbaytel.com
//http://my.tbaytel.net/tgallo/hp prime
BEGIN

local touch;
local X,Y;
local i,j,indx;
local done;
local difficulty;
local key;
local selectedColor;
local mouseUnclick;

//title screen
RECT_P(0,0,319,239,0,RGB(0,0,0));
TEXTOUT_P("SAMEGAME",129,90,2,RGB(255,0,0));
TEXTOUT_P("v1.4   2024",133,110,1,RGB(255,0,0));
TEXTOUT_P("by Tony Gallo",128,130,1,RGB(255,0,0));
wait(1.5);

//red, blue, yellow, green, pink
colorList:= {RGB(255,0,0),RGB(0,0,255),RGB(255,255,0),RGB(0,255,0),RGB(255,0,255)};

difficultyList:= {"Beginner", "Intermediate", "Advanced"};

CHOOSE(difficulty, "Choose Difficulty Level", "Beginner - 3 colors", "Intermediate - 4 colors", "Advanced - 5 colors");

if difficulty == 0 then
//clicked outside choose box - default to Beginner
   difficulty:=1;
end;

//clear screen
RECT_P(0,0,319,239,0,RGB(250,190,120));

//credits
TEXTOUT_P("SAMEGAME",10,5,2,RGB(0,0,0));
TEXTOUT_P("v1.4   2024",100,6,1,RGB(0,0,0));
TEXTOUT_P("by Tony Gallo",250,5,1,RGB(0,0,0));

//sidebar
TEXTOUT_P("Difficulty Level:",220,30,2,RGB(0,0,0));
TEXTOUT_P(difficultyList(difficulty),225,45,2,RGB(255,0,0));
TEXTOUT_P("Total Score:",220,70,2,RGB(0,0,0));
TEXTOUT_P("0",225,85,2,RGB(255,0,0));
TEXTOUT_P("Click Score:",220,110,2,RGB(0,0,0));
//TEXTOUT_P("0",225,125,2,RGB(255,0,0));
TEXTOUT_P("High Score:",220,150,2,RGB(0,0,0));
TEXTOUT_P("0",225,165,2,RGB(255,0,0));

boardCheck:=makelist(0,A,1,100,1);

highscore:=0;

done:= 0;
WHILE (done==0) DO

score:= 0;
UpdateScore();

clickscore := 0;

mouseUnclick:=1;
DrawBoard(difficulty);

//start in bottom left corner
highlightindex := 91;
HighlightMoved();


WHILE ISKEYDOWN(4)<>1 do
     wait(.01);
     touch:=mouse();
     key:=-1;

     key:=getkey;

     if key==2 or key==7 or key==8 or key==12 then
      MoveHighlight(key);
      //find adjacent squares with the same colour as the one selected
      HighlightMoved();
      continue;
     end;

     if key == 30 then
     //pressed ENTER
      if IsGroup(highlightindex) == 1 then
        UpdateScore();
        RemoveGroup();
        ShiftCircles();
        highlightindex:=91;
        HighlightMoved();
        if IsGameOver()==1 then
           key:=-1;
           while key<>28 and key<>42 and key<>4 do
             wait(.1);
             //touch:=mouse();
             key:=getkey;
           end;
           if key==28 or key==4 then
             done:=1;
           end;
           break;
        end;
      end;
     end;


     if size(touch(1)) then
        if touch(1,5)==0 then
           X:=B→R(touch(1,1));
           Y:=B→R(touch(1,2));

           if 10<=X<=209 and 20<=Y<=219 and mouseUnclick==1 THEN
           //pressed board with finger
               mouseUnclick:=0; //sets flag to stop processing mouse clicks until unclick has happened
               i:=iquo((X-10),20);
               j:=iquo((Y-20),20);
               highlightindex := 10*j + i + 1;
               if boardCheck(highlightindex) == 2 then
               //clicked within selected group, same as ENTER
                if IsGroup(highlightindex) == 1 then
                  UpdateScore();
                  RemoveGroup();
                  ShiftCircles();
                  highlightindex:=-1;                    
                  RECT_P(220,123,270,138,RGB(250,190,120),RGB(250,190,120)); //clear click score
                  if IsGameOver()==1 then
                     key:=-1;
                     while key<>28 and key<>42 and key<>4 do
                       wait(.1);
                       //touch:=mouse();
                       key:=getkey;
                     end;
                     if key==28 or key==4 then
                       done:=1;
                     end;
                     break;
                  end;
                end;
               else
                  HighlightMoved();
               end;
           end;

        end;
     else
       //touch is empty, mouse unclicked
       mouseUnclick:=1;
     end;

END;

if key==4 then
//pressed ESC to exit
  done:=1;
end;

ClearGameOver();
END;


END;

DrawBoard(difficulty)
begin
local I,J,colorNum;

//fill board with 0s for empty
//replace each spot with the number of the color (0-5)
boardColor:=makelist(0,A,1,100,1);


RECT_P(10,20,210,220,0,RGB(0,0,0));

FOR I FROM 0 to 9 DO
 FOR J FROM 0 to 9 DO
  colorNum:=RANDINT(1,difficulty+2);
  boardColor((J*10)+(I+1)) :=  colorNum;
  ARC_P(20+20*I,30+20*J,8,{colorList(colorNum),colorList(colorNum)});
 END;
END;

end;


HighlightMoved()
begin
local selectedColor;

      selectedColor := boardColor(highlightindex);
      ClearBoardCheck();
      CheckSquare(highlightindex, selectedColor);
      ClickScore();
end;


ColorSquare(indx, highlight)
begin
local I,J;
local color,squarecolor;

   I := irem(indx-1,10);
   J := iquo(indx-1,10);
   color := colorList(boardColor(indx));

   if highlight == 1 then
     if indx == highlightindex then
       squarecolor := RGB(175,175,175);
     else
       squarecolor := RGB(255,255,255);
     end;
   else
     squarecolor := RGB(0,0,0);
   end;

   RECT_P(10+20*I,20+20*J,30+20*I,40+20*J,squarecolor,squarecolor);
   ARC_P(20+20*I,30+20*J,8,{color,color});

end;


MoveHighlight(key)
begin

   CASE
      if key == 2 then
         if 1<= highlightindex <= 10 then
            highlightindex := highlightindex + 90;
         else
            highlightindex := highlightindex - 10;
         end;
      end;

      if key == 7 then
         if irem(highlightindex,10) == 1 then
            highlightindex := highlightindex + 9;
         else
            highlightindex := highlightindex - 1;
         end;
      end;

      if key == 8 then
         if irem(highlightindex,10) == 0 then
            highlightindex := highlightindex - 9;
         else
            highlightindex := highlightindex + 1;
         end;
      end;

      if key == 12 then
         if 91<= highlightindex <= 100 then
            highlightindex := highlightindex - 90;
         else
            highlightindex := highlightindex + 10;
         end;
      end;

   END;

   if boardColor(highlightindex) == 0 then
      MoveHighlight(key);
   end;

end;


CheckSquare(indx, colorNum)
begin
   if boardCheck(indx) > 0 or boardColor(indx) == 0 then
     //already checked
     return 0;
   end;

  
   if boardColor(indx) == colorNum then
      boardCheck(indx) := 2;
      ColorSquare(indx,1);
      AdjacentSquares(indx, colorNum);
      return 1;
   else
     boardCheck(indx) := 1;
     return 0;
   end;
end;


ClickScore()
begin
 local I;
 local adjcount;
 
 adjcount := 0;
  FOR I FROM 1 to 100 DO
   if boardCheck(I) == 2 then 
     adjcount := adjcount + 1;
   end;
  END;

 clickscore := (adjcount - 2)^2;
 
 RECT_P(220,123,270,138,RGB(250,190,120),RGB(250,190,120));

 if (adjcount >= 2) then
   TEXTOUT_P(IntToString(clickscore),225,125,2,RGB(255,0,0));
 end
end;


AdjacentSquares(indx, colorNum)
begin
     CASE
   //top left corner
   if indx == 1 then
     CheckSquare(indx+1, colorNum);
     CheckSquare(indx+10, colorNum);
   end;

   //top row
   if 2 <= indx <= 9 then
     CheckSquare(indx-1, colorNum);
     CheckSquare(indx+1, colorNum);
     CheckSquare(indx+10, colorNum);
   end;

   //top right corner
   if indx == 10 then
     CheckSquare(indx-1, colorNum);
     CheckSquare(indx+10, colorNum);
   end;

   //bottom left corner
   if indx == 91 then
     CheckSquare(indx-10, colorNum);
     CheckSquare(indx+1, colorNum);
   end;

   //bottom row
   if 92 <= indx <= 99 then
     CheckSquare(indx-10, colorNum);
     CheckSquare(indx-1, colorNum);
     CheckSquare(indx+1, colorNum);
   end;

   //bottom right corner
   if indx == 100 then
     CheckSquare(indx-10, colorNum);
     CheckSquare(indx-1, colorNum);
   end;

   //farmost left column
   if irem(indx,10) == 1 then
     CheckSquare(indx-10, colorNum);
     CheckSquare(indx+1, colorNum);
     CheckSquare(indx+10, colorNum);
   end;

   //farmost right column
   if irem(indx,10) == 0 then
     CheckSquare(indx-10, colorNum);
     CheckSquare(indx-1, colorNum);
     CheckSquare(indx+10, colorNum);
   end;

   //everywhere else (in the middle)
     CheckSquare(indx-10, colorNum);
     CheckSquare(indx-1, colorNum);
     CheckSquare(indx+1, colorNum);
     CheckSquare(indx+10, colorNum);
 
   END;
end;


ClearBoardCheck()
begin
local I;

   FOR I FROM 1 to 100 DO
    if boardCheck(I) == 2 then
      ColorSquare(I,0);
    end;
    boardCheck(I) := 0;
   END

end;


UpdateScore()
begin
   score := score + clickscore;
   RECT_P(220,83,270,98,RGB(250,190,120),RGB(250,190,120));
   TEXTOUT_P(IntToString(score),225,85,2,RGB(255,0,0));
end;


UpdateHighScore()
begin
   if score > highscore then
     highscore:=score;
     RECT_P(220,163,270,178,RGB(250,190,120),RGB(250,190,120));
     TEXTOUT_P(IntToString(score),225,165,2,RGB(255,0,0));
   end;
end;


RemoveGroup()
begin
local I,J,K;

   FOR K FROM 1 to 100 DO
    if boardCheck(K) == 2 then
      boardColor(K) := 0;
      boardCheck(K) := 0;

      I := irem(K-1,10);
      J := iquo(K-1,10);
      RECT_P(10+20*I,20+20*J,30+20*I,40+20*J,RGB(0,0,0),RGB(0,0,0));
    end;
   END

end;


ShiftCircles()
begin
local I,J,K,L;
  //first falling down to fill in empty spots
  FOR I FROM 1 to 10 DO
    FOR J FROM 0 to 8 DO
      K := 10*(9-J) + I;
      if boardColor(K) == 0 then
      //blacked out
        L := K-10;
        while L > 0 do
          if boardColor(L) <> 0 then
            while (L > 0) and (boardColor(L) <> 0) do
              boardColor(K) := boardColor(L);
              ColorCircle(K, boardColor(L));
              boardColor(L) := 0;
              BlackSquare(L);
              K := K-10;
              L := L-10;
            end;
          else
            L := L-10;
          end;
        end;
      end;
    END;
  END;

  //now move columns to the left to fill in empty columns

  FOR I FROM 1 to 9 DO
    if boardColor(90+I) == 0 then
    //blacked out
      K := I+1;
      while (K <= 10) do
        if (boardColor(90+K) <> 0) then
         FOR J FROM 0 to 9 DO
           if boardColor((J*10)+K) <> 0 then
             boardColor((J*10)+I) := boardColor((J*10)+K);
             ColorCircle((J*10)+I, boardColor((J*10)+K));
             boardColor((J*10)+K) := 0;
             BlackSquare((J*10)+K);
           end;
         END;
         BREAK;
        end;
        K := K+1;
      end;
    end;
  END;

end;


IsGroup(indx)
begin
local colorNum;

  colorNum := boardColor(indx);
  CASE

   //top left corner
   if indx == 1 then
     if ((boardColor(indx+1) == colorNum) or (boardColor(indx+10) == colorNum)) then
        return 1;
     end;
   end;

   //top row
   if 2 <= indx <= 9 then
     if ((boardColor(indx-1) == colorNum) or (boardColor(indx+1) == colorNum) or (boardColor(indx+10) == colorNum)) then
        return 1;
     end;
   end;

   //top right corner
   if indx == 10 then
     if ((boardColor(indx-1) == colorNum) or (boardColor(indx+10) == colorNum)) then
        return 1;
     end;
   end;

   //bottom left corner
   if indx == 91 then
     if ((boardColor(indx-10) == colorNum) or (boardColor(indx+1) == colorNum)) then
        return 1;
     end;
   end;

   //bottom row
   if 92 <= indx <= 99 then
     if ((boardColor(indx-10) == colorNum) or (boardColor(indx-1) == colorNum) or (boardColor(indx+1) == colorNum)) then
        return 1;
     end;
   end;

   //bottom right corner
   if indx == 100 then
     if ((boardColor(indx-10) == colorNum) or (boardColor(indx-1) == colorNum)) then
        return 1;
     end;
   end;

   //farmost left column
   if irem(indx,10) == 1 then
     if ((boardColor(indx-10) == colorNum) or (boardColor(indx+1) == colorNum) or (boardColor(indx+10) == colorNum)) then
        return 1;
     end;
   end;

   //farmost right column
   if irem(indx,10) == 0 then
     if ((boardColor(indx-10) == colorNum) or (boardColor(indx-1) == colorNum) or (boardColor(indx+10) == colorNum)) then
        return 1;
     end;
   end;

   //everywhere else (in the middle)
   if ((boardColor(indx-10) == colorNum) or (boardColor(indx-1) == colorNum) or (boardColor(indx+1) == colorNum) or (boardColor(indx+10) == colorNum)) then
      return 1;
   end;


    return 0;

  END;

end;



ColorCircle(indx, colorNum)
begin
local I,J;
   I := irem(indx-1,10);
   J := iquo(indx-1,10);
   ARC_P(20+20*I,30+20*J,8,{colorList(colorNum),colorList(colorNum)});
end;

BlackSquare(indx)
begin
local I,J;


   I := irem(indx-1,10);
   J := iquo(indx-1,10);

   RECT_P(10+20*I,20+20*J,30+20*I,40+20*J,RGB(0,0,0),RGB(0,0,0));

end;

IsGameOver()
begin
local I;
local gameover;

 gameover := 1;

 //search board for groups of 2 or more
 FOR I FROM 1 to 100 DO
   if (boardColor(I) <> 0) then
     if (IsGroup(I) == 1) then
       gameover := 0;
       break;
     end;
   end;
 END;

 if gameover == 1 then
    UpdateHighScore();
    TEXTOUT_P("GAME OVER",225,190,2,RGB(0,0,0));
    TEXTOUT_P("Play Again Y/N",220,205,2,RGB(0,0,0));
    return 1;
 else
    return 0;
 end;
end;


ClearGameOver()
begin
  RECT_P(220,190,300,230,RGB(250,190,120),RGB(250,190,120));
end;


IntToString(integer)
begin
local rem;
local string = "";
local negative = 0;

if integer == 0 then
   return "0";
end;

if integer < 0 then
   negative := 1;
  integer := integer * (-1);
end;

while integer > 0 do
  rem := irem(integer,10);
  string := DigitToChar(rem) + string ;
  integer := (integer - rem)/10;
end;

if negative == 1 then
  string:= "-" + string;
end;
return string;

end;


DigitToChar(digit)
begin

if digit == 0 then
  return "0";
end;

if digit == 1 then
  return "1";
end;

if digit == 2 then
  return "2";
end;

if digit == 3 then
  return "3";
end;

if digit == 4 then
  return "4";
end;

if digit == 5 then
  return "5";
end;

if digit == 6 then
  return "6";
end;

if digit == 7 then
  return "7";
end;

if digit == 8 then
  return "8";
end;

if digit == 9 then
  return "9";
end;

end;